使用 getopts 处理长短命令行选项答案 您所在的位置:网站首页 getopts 长参数 使用 getopts 处理长短命令行选项答案

使用 getopts 处理长短命令行选项答案

2023-04-07 10:45| 来源: 网络整理| 查看: 265

getopt 和getopts 是不同的野兽,人们似乎对他们的所作所为有点误解。 getopts 是bash 的内置命令,用于循环处理命令行选项,并将找到的每个选项和值依次分配给内置变量,以便您进一步处理它们。然而,getopt 是一个外部实用程序,它实际上并没有为您处理您的选项,例如bash getopts、Perl Getopt 模块或 Python optparse/argparse 模块都可以。 getopt 所做的只是规范化传入的选项——即将它们转换为更标准的形式,以便 shell 脚本更容易处理它们。例如,getopt 的应用程序可能会转换以下内容:

myscript -ab infile.txt -ooutfile.txt

进入这个:

myscript -a -b -o outfile.txt infile.txt

您必须自己进行实际处理。如果您对指定选项的方式进行各种限制,则根本不必使用getopt:

每个参数只放一个选项; 所有选项都在任何位置参数之前(即非选项参数); 对于带有值的选项(例如上面的-o),该值必须作为单独的参数(在空格之后)。

为什么使用getopt 而不是getopts?基本原因是只有 GNU getopt 为您提供对长名称命令行选项的支持。1(GNU getopt 是 Linux 上的默认设置。Mac OS X 和 FreeBSD 带有基本的并且不是很有用getopt,但可以安装 GNU 版本;见下文。)

例如,这是一个使用 GNU getopt 的示例,来自我的一个名为 javawrap 的脚本:

# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this # separately; see below. TEMP=$(getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \ -n 'javawrap' -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around '$TEMP': they are essential! eval set -- "$TEMP" VERBOSE=false DEBUG=false MEMORY= DEBUGFILE= JAVA_MISC_OPT= while true; do case "$1" in -v | --verbose ) VERBOSE=true; shift ;; -d | --debug ) DEBUG=true; shift ;; -m | --memory ) MEMORY="$2"; shift 2 ;; --debugfile ) DEBUGFILE="$2"; shift 2 ;; --minheap ) JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;; --maxheap ) JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;; -- ) shift; break ;; * ) break ;; esac done

这使您可以指定--verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt" 或类似的选项。调用getopt 的效果是将选项规范化为--verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt",以便您可以更轻松地处理它们。 "$1" 和 "$2" 周围的引用很重要,因为它可以确保正确处理带有空格的参数。

如果您删除前 9 行(从 eval set 行开始的所有内容),代码将仍然有效!但是,您的代码在接受哪些类型的选项时会更加挑剔:特别是,您必须以上述“规范”形式指定所有选项。但是,通过使用getopt,您可以对单字母选项进行分组,使用更短的非歧义形式的长选项,使用--file foo.txt 或--file=foo.txt 样式,使用-m 4096 或@987654355 @style,以任意顺序混合选项和非选项等。getopt 如果发现无法识别或模棱两可的选项,也会输出错误消息。

注意:getopt 实际上有两个完全不同的版本,基本的getopt 和 GNU getopt,具有不同的功能和不同的调用约定。2 Basic getopt 非常糟糕:它不仅不能处理长选项,甚至不能处理参数或空参数中的嵌入空格,而getopts 确实做到了这一点。上面的代码在基本的getopt 中不起作用。 GNU getopt 默认安装在 Linux 上,但在 Mac OS X 和 FreeBSD 上需要单独安装。在 Mac OS X 上,安装 MacPorts (http://www.macports.org),然后执行 sudo port install getopt 以安装 GNU getopt(通常安装到 /opt/local/bin),并确保 /opt/local/bin 在您的 shell 路径中位于 /usr/bin 之前。在 FreeBSD 上,安装 misc/getopt。

为您自己的程序修改示例代码的快速指南:在前几行中,除了调用getopt 的行之外,所有的都是“样板”,应该保持不变。您应该在-n 之后更改程序名称,在-o 之后指定短选项,在--long 之后指定长选项。在取值的选项后面加一个冒号。

最后,如果您看到的代码只有 set 而不是 eval set,那么它是为 BSD getopt 编写的。您应该将其更改为使用eval set 样式,它适用于getopt 的两个版本,而普通的set 不适用于GNU getopt。

1实际上,ksh93 中的 getopts 支持长名称选项,但是这个 shell 不像 bash 那样经常使用。在zsh 中,使用zparseopts 获取此功能。

2从技术上讲,“GNU getopt”是用词不当;这个版本实际上是为 Linux 而不是 GNU 项目编写的。但是,它遵循所有 GNU 约定,并且通常使用术语“GNU getopt”(例如在 FreeBSD 上)。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有